using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System.Diagnostics;
using System.Text;

namespace hao_Common.Logging.Middleware
{
    /// <summary>
    /// 请求日志中间件
    /// </summary>
    public class RequestLoggingMiddleware : IMiddleware
    {
        private readonly ILogger<RequestLoggingMiddleware> _logger;

        public RequestLoggingMiddleware(ILogger<RequestLoggingMiddleware> logger)
        {
            _logger = logger;
        }

        public async Task InvokeAsync(HttpContext context, RequestDelegate next)
        {
            var stopwatch = Stopwatch.StartNew();
            var requestId = Guid.NewGuid().ToString();
            
            // 添加请求ID到响应头
            context.Response.Headers.Add("X-Request-Id", requestId);
            
            // 记录请求信息
            await LogRequestAsync(context, requestId);
            
            try
            {
                await next(context);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "请求处理异常 RequestId: {RequestId}", requestId);
                throw;
            }
            finally
            {
                stopwatch.Stop();
                // 记录响应信息
                LogResponse(context, requestId, stopwatch.ElapsedMilliseconds);
            }
        }

        /// <summary>
        /// 记录请求信息
        /// </summary>
        private async Task LogRequestAsync(HttpContext context, string requestId)
        {
            var request = context.Request;
            
            var requestInfo = new
            {
                RequestId = requestId,
                Method = request.Method,
                Path = request.Path.Value,
                QueryString = request.QueryString.Value,
                Headers = GetHeaders(request.Headers),
                UserAgent = request.Headers["User-Agent"].ToString(),
                RemoteIpAddress = context.Connection.RemoteIpAddress?.ToString(),
                Body = await GetRequestBodyAsync(request)
            };

            _logger.LogInformation("HTTP请求开始 {@RequestInfo}", requestInfo);
        }

        /// <summary>
        /// 记录响应信息
        /// </summary>
        private void LogResponse(HttpContext context, string requestId, long elapsedMs)
        {
            var response = context.Response;
            
            var responseInfo = new
            {
                RequestId = requestId,
                StatusCode = response.StatusCode,
                ContentType = response.ContentType,
                ElapsedMilliseconds = elapsedMs,
                Headers = GetHeaders(response.Headers)
            };

            var logLevel = response.StatusCode >= 400 ? LogLevel.Warning : LogLevel.Information;
            _logger.Log(logLevel, "HTTP请求完成 {@ResponseInfo}", responseInfo);
        }

        /// <summary>
        /// 获取请求体内容
        /// </summary>
        private async Task<string?> GetRequestBodyAsync(HttpRequest request)
        {
            if (!ShouldLogRequestBody(request))
                return null;

            try
            {
                request.EnableBuffering();
                var buffer = new byte[Convert.ToInt32(request.ContentLength)];
                await request.Body.ReadAsync(buffer, 0, buffer.Length);
                request.Body.Position = 0;
                
                var body = Encoding.UTF8.GetString(buffer);
                return body.Length > 1000 ? body.Substring(0, 1000) + "..." : body;
            }
            catch
            {
                return "[无法读取请求体]";
            }
        }

        /// <summary>
        /// 判断是否应该记录请求体
        /// </summary>
        private static bool ShouldLogRequestBody(HttpRequest request)
        {
            if (request.ContentLength == null || request.ContentLength == 0)
                return false;

            if (request.ContentLength > 10000) // 大于10KB不记录
                return false;

            var contentType = request.ContentType?.ToLower();
            if (contentType == null)
                return false;

            // 只记录JSON和表单数据
            return contentType.Contains("application/json") || 
                   contentType.Contains("application/x-www-form-urlencoded") ||
                   contentType.Contains("text/");
        }

        /// <summary>
        /// 获取请求头信息（过滤敏感信息）
        /// </summary>
        private static Dictionary<string, string> GetHeaders(IHeaderDictionary headers)
        {
            var sensitiveHeaders = new[] { "authorization", "cookie", "x-api-key", "x-auth-token" };
            
            return headers
                .Where(h => !sensitiveHeaders.Contains(h.Key.ToLower()))
                .ToDictionary(h => h.Key, h => h.Value.ToString());
        }
    }
}